﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management;
using System.Text;
using WMI.NET.Abstracts;
using WMI.NET.CIM;

namespace WMI.NET.InstalledApplications
{
    /// <summary>
    /// The Win32_Product WMI class represents products as they are installed by Windows Installer. A product generally correlates to one installation package.
    /// </summary>
    public class Win32_Product : CIM_Product
    {

        private Nullable<UInt16> _AssignmentType;
        private string _InstallDate;
        private Nullable<DateTimeOffset> _InstallDate2;
        private string _InstallLocation;
        private Nullable<Int16> _InstallState;
        private string _HelpLink;
        private string _HelpTelephone;
        private string _InstallSource;
        private string _Language;
        private string _LocalPackage;
        private string _PackageCache;
        private string _PackageCode;
        private string _PackageName;
        private string _ProductID;
        private string _RegOwner;
        private string _RegCompany;
        private string _Transforms;
        private string _URLInfoAbout;
        private string _URLUpdateInfo;
        private Nullable<UInt32> _WordCount;

        /// <summary>
        /// Assignment type of the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public Nullable<UInt16> AssignmentType { get { return _AssignmentType; } } //TODO enum

        /// <summary>
        /// This property is no longer supported for Win32_Product. Instead, use the InstallDate2 property, which is in the WMI CIM_DATETIME format. 
        /// </summary>
        public string InstallDate { get { return _InstallDate; } }

        /// <summary>
        /// Date that this product was installed on the system. This property does not require a value to indicate that the object is installed. For more information about WMI dates and times, see Date and Time Format. 
        /// </summary>
        public Nullable<DateTimeOffset> InstallDate2 { get { return _InstallDate2; } }

        /// <summary>
        /// Location of the installed product.
        /// </summary>
        public string InstallLocation { get { return _InstallLocation; } }

        /// <summary>
        /// Installed state of the product.
        /// </summary>
        public Nullable<Int16> InstallState { get { return _InstallState; } } //TODO enum

        /// <summary>
        /// The support link for the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string HelpLink { get { return _HelpLink; } }

        /// <summary>
        /// The support telephone for the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string HelpTelephone { get { return _HelpTelephone; } }

        /// <summary>
        /// The installation source directory of the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string InstallSource { get { return _InstallSource; } }

        /// <summary>
        /// The language of the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string Language { get { return _Language; } }

        /// <summary>
        /// The location of the locally cached package for this product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string LocalPackage { get { return _LocalPackage; } }

        /// <summary>
        /// Location of the locally cached package for this product.
        /// </summary>
        public string PackageCache { get { return _PackageCache; } }

        /// <summary>
        /// The identifier for the package from which this product was installed.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string PackageCode { get { return _PackageCode; } }

        /// <summary>
        /// The original package name for the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string PackageName { get { return _PackageName; } }

        /// <summary>
        /// The product ID.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string ProductID { get { return _ProductID; } }

        /// <summary>
        /// The owner registered to use the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string RegOwner { get { return _RegOwner; } }

        /// <summary>
        /// The company registered to use the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string RegCompany { get { return _RegCompany; } }

        /// <summary>
        /// The transforms of the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string Transforms { get { return _Transforms; } }

        /// <summary>
        /// The URL information for the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string URLInfoAbout { get { return _URLInfoAbout; } }

        /// <summary>
        /// The URL update information the product.
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public string URLUpdateInfo { get { return _URLUpdateInfo; } }

        /// <summary>
        /// Number of words in the summary information for the product. 
        /// Windows Server 2003:  This property is not available. 
        /// </summary>
        public Nullable<UInt32> WordCount { get { return _WordCount; } }



        /// <summary>
        /// The Admin WMI class method performs an administrative install of an associated Win32_Product using the installation package provided through the PackageLocation parameter, and any supplied command line options.
        /// </summary>
        /// <param name="PackageLocation">Path to the package to be administered.</param>
        /// <param name="TargetLocation">Location for the administrative image to be installed.</param>
        /// <param name="Options">Command line options for the upgrade. These should be in the form of property=setting.</param>
        /// <returns>//TODO Enum</returns>
        public UInt32 Admin(string PackageLocation, string TargetLocation, string Options) { throw new NotImplementedException(); }

        /// <summary>
        /// The Advertise WMI class method advertises an associated Win32_Product instance using the installation package provided through the PackageLocation parameter and any supplied command line options.
        /// </summary>
        /// <param name="PackageLocation">The path to the package to be advertised.</param>
        /// <param name="Options">Command line options for the advertisement. Format as property=setting.</param>
        /// <returns></returns>
        public UInt32 Advertise(string PackageLocation, string Options) { throw new NotImplementedException(); }

        /// <summary>
        /// The Configure WMI class method configures the associated instance of Win32_Product to the specified install state and level.
        /// </summary>
        /// <param name="InstallState">Installation state. //TODO Enum</param>
        /// <param name="InstallLevel">Installation level. //TODO Enum</param>
        /// <param name="Options">The command line options for configure. These should be in the form of property=setting.</param>
        /// <returns></returns>
        public UInt32 Configure(UInt32 InstallState, UInt32 InstallLevel, string Options) { throw new NotImplementedException(); }


        /// <summary>
        /// The static Install WMI class method installs an associated Win32_Product instance using the installation package provided through the PackageLocation parameter, and any supplied command line options.
        /// </summary>
        /// <param name="PackageLocation">The path to the package to be installed.</param>
        /// <param name="Options">The command line options for the installation. Format as property=setting.</param>
        /// <param name="AllUsers">This parameter value must be present, but it is ignored. True is the recommended value.</param>
        /// <returns>//TODO Enum</returns>
        public UInt32 Install(string PackageLocation, string Options, Boolean AllUsers) { throw new NotImplementedException(); }

        /// <summary>
        /// Using the specified reinstallation mode, the Reinstall WMI class method reinstalls the associated instance of Win32_Product.
        /// </summary>
        /// <param name="ReinstallMode"></param>
        /// <returns>The reinstallation mode. //TODO Enum</returns>
        public UInt32 Reinstall(UInt32 ReinstallMode) { throw new NotImplementedException(); }

        /// <summary>
        /// The Uninstall WMI class method uninstalls the associated instance of Win32_Product.
        /// </summary>
        /// <returns></returns>
        public UInt32 Uninstall() { throw new NotImplementedException(); }

        /// <summary>
        /// The Upgrade WMI class method upgrades the associated Win32_Product instance using the upgrade package provided through the PackageLocation parameter and any supplied command line options.
        /// </summary>
        /// <param name="PackageLocation">The path to the package that contains the upgrade.</param>
        /// <param name="Options">The command line options for the upgrade. Format as property=setting.</param>
        /// <returns></returns>
        public UInt32 Upgrade(string PackageLocation, string Options) { throw new NotImplementedException(); }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="mbo"></param>
        public Win32_Product(ManagementBaseObject mbo)
            : base(mbo)
        {
            _AssignmentType = mbo.GetUshortValue("AssignmentType");
            _InstallDate = mbo.GetStringValue("InstallDate");
            _InstallDate2 = mbo.GetDateTimeOffsetValue("InstallDate2" , Consts.DateTimeFormat);
            _InstallLocation = mbo.GetStringValue("InstallLocation");
            _InstallState = mbo.GetShortValue("InstallState");
            _HelpLink = mbo.GetStringValue("HelpLink");
            _HelpTelephone = mbo.GetStringValue("HelpTelephone");
            _InstallSource = mbo.GetStringValue("InstallSource");
            _Language = mbo.GetStringValue("Language");
            _LocalPackage = mbo.GetStringValue("LocalPackage");
            _PackageCache = mbo.GetStringValue("PackageCache");
            _PackageCode = mbo.GetStringValue("PackageCode");
            _PackageName = mbo.GetStringValue("PackageName");
            _ProductID = mbo.GetStringValue("ProductID");
            _RegOwner = mbo.GetStringValue("RegOwner");
            _RegCompany = mbo.GetStringValue("RegCompany");
            _Transforms = mbo.GetStringValue("Transforms");
            _URLInfoAbout = mbo.GetStringValue("URLInfoAbout");
            _URLUpdateInfo = mbo.GetStringValue("URLUpdateInfo");
            _WordCount = mbo.GetUIntValue("WordCount");
        }

    }


    /// <summary>
    /// 
    /// </summary>
    public class GetWin32_Products : Win32Collection<Win32_Product>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override ReadOnlyCollection<Win32_Product> GetCollection()
        {
            List<Win32_Product> tempCollection = new List<Win32_Product>();

            foreach (var s in searcher.Get())
            {

                Win32_Product tempListItem = new Win32_Product(s);
                tempCollection.Add(tempListItem);
            }

            return tempCollection.AsReadOnly();
        }

        /// <summary>
        /// 
        /// </summary>
        public GetWin32_Products() : base("SELECT * FROM Win32_Product") { }

    }

}
